package dragon.core.io;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.List;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;

import dragon.core.exception.ExceptionHandler;

/**
 * 利用apach下的ant.jar包下工具实现文件(解)压缩
 */
public class ZipFiles {

	/**
	 * 压缩文件
	 * 
	 * @param source
	 *            待压缩文件路径 <code>java.lang.String</code>
	 * @param target
	 *            压缩后的目标文件路径 <code>java.lang.String</code>
	 */
	public static void zip(String source, String target) throws ExceptionHandler {

		// 获取根路径
		String root = source.substring(0, source.lastIndexOf("\\") + 1);

		List<File> files = FileHandler.getFiles(source, 0, true);

		if (files.size() == 0) {
			return;
		}

		try {

			// 目标文件
			File targetFile = new File(target);
			if (targetFile.exists()) {
				targetFile.delete();
			}
			targetFile.createNewFile();

			BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile));
			ZipOutputStream zos = new ZipOutputStream(bos);

			FileInputStream fis = null;
			BufferedInputStream bis = null;

			final int BUFFER = 10240;
			byte[] b = new byte[BUFFER];

			for (File file : files) {
				if (file.getAbsolutePath().equals(target)) {
					continue;
				}
				String entryName = file.getAbsolutePath().substring(root.length());
				if (file.isDirectory()) {
					entryName = entryName + "/";// 对目录的特别设置，需要注意
				}
				ZipEntry entry = new ZipEntry(entryName);
				zos.putNextEntry(entry);

				// 如果是文件
				if (file.isFile()) {
					fis = new FileInputStream(file);
					bis = new BufferedInputStream(fis);
					int len = 0;
					while ((len = bis.read(b, 0, BUFFER)) != -1) {
						zos.write(b, 0, len);
					}

					bis.close();
				}

				// 关闭当前条目
				zos.closeEntry();
			}
			zos.flush();
			zos.close();

		} catch (FileNotFoundException e) {
			throw new ExceptionHandler(e);
		} catch (IOException e) {
			throw new ExceptionHandler(e);
		}

	}

	/**
	 * 功能：解压缩
	 * 
	 * @param zipFilename
	 *            zip文件
	 * @param destPath
	 *            解压缩路径
	 * @throws java.lang.Exception
	 */
	@SuppressWarnings("rawtypes")
	public static void unZip(String zipFilename, String destPath) throws ExceptionHandler {

		ZipFile zip = null;
		try {
			zip = new ZipFile(zipFilename, "GB2312");
		} catch (IOException e) {
			throw new ExceptionHandler(e);
		}// 采用 GB2312
			// 字符集编码进行解压压缩文件
		Enumeration enu = zip.getEntries();// 得到压缩文件夹中的所有文件
		while (enu.hasMoreElements()) {
			ZipEntry entry = (ZipEntry) enu.nextElement();// 获取到一个压缩文件中的文件(夹)
			String file = destPath + entry.getName();
			try {
				write(zip, entry, file);
			} catch (Exception e) {
				throw new ExceptionHandler(e);
			}
		}
		if (zip != null) {
			try {
				zip.close();
			} catch (IOException e) {
				throw new ExceptionHandler(e);
			}
			zip = null;
		}

	}

	/**
	 * 功能：将解压缩之后的文件写入目录
	 * 
	 * @param zip
	 *            压缩文件
	 * @param entry
	 *            压缩文件实体——压缩文件中的文件
	 * @param fileLocation
	 *            解压缩之后的文件路径
	 * @throws Exception
	 */
	private static void write(ZipFile zip, ZipEntry entry, String file) throws Exception {
		if (entry.isDirectory()) {
			File f = new File(file);
			f.mkdirs();// 创建目录
		} else {
			File f = new File(file);
			if (!f.getParentFile().exists()) {
				f.getParentFile().mkdirs();
			}
			FileOutputStream fos = new FileOutputStream(f);
			byte[] buffer = new byte[8196];
			InputStream is = zip.getInputStream(entry);
			for (int len = is.read(buffer, 0, buffer.length); len != -1; len = is.read(buffer, 0, 8196)) {
				fos.write(buffer, 0, len);
			}
			fos.close();
		}
	}

}
